﻿using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

using Microsoft.Xna.Framework;
using XNA_2DFramwork;

namespace Zeus.Web.Services
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class CompilationWCFService
    {
        public CompilationWCFService()
        {
        }
        private string GetMainClass(List<string> filesName,List<string> Codes)
        {
            for (int i = 0; i < Codes.Count; i++)
            {
                if (Codes[i].Contains("Main(") && !Codes.Contains("\""))
                {
                    return "Zeus."+filesName[i];
                }
            }
            return "Not Found";
        }
        [OperationContract]
        public List<ErrorItem> GetErrors(List<string> filesName,List<string> Codes,bool Is2D)
        {
            List<ErrorItem> ErrorList = new List<ErrorItem>();
            IDictionary<string, string> providerOptions = new Dictionary<string, string>();
            providerOptions["CompilerVersion"] = "v3.5"; // 3shan lw 7abeet azawed lel XBOX
            CSharpCodeProvider codeProvider = new CSharpCodeProvider(providerOptions);
            ICodeCompiler icc = codeProvider.CreateCompiler();
            CompilerParameters parameters = new CompilerParameters();

            //parameters.GenerateInMemory = true;
            //parameters.GenerateExecutable = true;
            //parameters.OutputAssembly = "game1.exe";

            if (codeProvider.Supports(GeneratorSupport.EntryPointMethod))
            {
                // Specify the class that contains 
                // the main method of the executable.
                parameters.MainClass = GetMainClass(filesName,Codes);
            }

            #region Adding Referances
            string path = Assembly.GetAssembly(typeof(Microsoft.Xna.Framework.Game)).Location;
            parameters.ReferencedAssemblies.Add(path);
            path = Assembly.GetAssembly(typeof(Microsoft.Xna.Framework.Audio.AudioCategory)).Location;
            parameters.ReferencedAssemblies.Add(path);
            path = Assembly.GetAssembly(typeof(System.Linq.Enumerable)).Location;
            parameters.ReferencedAssemblies.Add(path);
            path = Assembly.GetAssembly(typeof(DemoBaseXNA.PhysicsSimulatorView)).Location;
            parameters.ReferencedAssemblies.Add(path);
            path = Assembly.GetAssembly(typeof(System.Uri)).Location;
            parameters.ReferencedAssemblies.Add(path);
            path = Assembly.GetAssembly(typeof(FarseerGames.FarseerPhysics.PhysicsSimulator)).Location;
            parameters.ReferencedAssemblies.Add(path);
            if (Is2D)
            {
                path = Assembly.GetAssembly(typeof (XNA_2DFramwork.Sound)).Location;
                parameters.ReferencedAssemblies.Add(path);
            }
            if (!Is2D)
            {
                path = Assembly.GetAssembly(typeof (XNA_3DFramWork.GameObject)).Location;
                parameters.ReferencedAssemblies.Add(path);
            }

            #endregion

            CompilerResults MainErrors = icc.CompileAssemblyFromSourceBatch(parameters, Codes.ToArray());

            #region Get Error File
            if (MainErrors.Errors.Count > 0)
            {
                for (int i = 0; i < Codes.Count; i++)   // halef fiha 3ala kol el files
                {
                    CompilerResults FileErrors = icc.CompileAssemblyFromSource(parameters, Codes[i]);
                    if (FileErrors.Errors.Count > 0)
                    {
                        for (int j = 0; j < MainErrors.Errors.Count; j++) // halef fiha 3la elli tale3li mn codes[i]
                        {
                            for (int k = 0; k < FileErrors.Errors.Count; k++) // halef 3ala elli tale3li mn el main
                            {
                                if (FileErrors.Errors[k].Column == MainErrors.Errors[j].Column &&
                                        FileErrors.Errors[k].ErrorNumber == MainErrors.Errors[j].ErrorNumber &&
                                        FileErrors.Errors[k].ErrorText == MainErrors.Errors[j].ErrorText &&
                                        FileErrors.Errors[k].Line == MainErrors.Errors[j].Line)
                                {
                                    ErrorItem item = new ErrorItem();
                                    item.ErrorLine = MainErrors.Errors[j].Line;
                                    item.ErrorNumber = MainErrors.Errors[j].ErrorNumber;
                                    item.ErrorText = MainErrors.Errors[j].ErrorText;
                                    item.ErrorColumn = MainErrors.Errors[j].Column;
                                    item.ErrorFile = filesName[i];
                                    ErrorList.Add(item);
                                }
                            }
                        }
                    }
                }
            }
            #endregion

            return ErrorList;
        }
    }

    public class ErrorItem
    {
        public long ErrorLine;
        public string ErrorNumber;
        public string ErrorText;
        public string ErrorFile;
        public long ErrorColumn;
    }
}
